/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core;

import datamodel.District;
import java.util.Vector;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import network.Connection;
import network.packets.DistrictStatisticResponce;
import network.packets.Packet;

/**
 *
 * @author Kvest
 */
public class DistrictsManager 
{
    public static final long UNKNOWN_TIME = 0;
    private static final String RMS_DISTRICTS_NAME = "districts";
    private static final int LAST_UPDATE_TIME_KEY = -1;
    
    private static DistrictsManager manager = null;;
    private static final Object lock = new Object();
   
    private long serverUpdateTime;
    private long latsUpdateTime;
    private Vector districts;

    private ChangeNotifier changeNotifier; 
    
    public static DistrictsManager getDistrictsManager()
    {
        synchronized(lock)
        {
            if (manager == null)
            {
                manager = new DistrictsManager();
            }
        }
        
        return manager;
    }
    
    private DistrictsManager()
    {
        latsUpdateTime = UNKNOWN_TIME;
        serverUpdateTime = UNKNOWN_TIME;
        districts = new Vector();
        
        //Подписываемся на пакеты о количестве заказов на стоянке и о порядке отображения стоянок
        Connection.getConnection().setPacketListener(Packet.DISTRICTS_STATISTIC_RESPONCE, new Connection.PacketNotifier()
        {
            public void incomingPacket(Packet packet)
            {
                DistrictStatisticResponce responce = (DistrictStatisticResponce)packet;

                District district;
                boolean changed = false;
                for (int i = 0; i < responce.size(); ++i)
                {
                    district = getDistrictById(responce.getItem(i).id);
                    if (district != null)
                    {
                        district.setOrdersCount(responce.getItem(i).ordersCount);
                        district.setDriversCount(responce.getItem(i).driversCount);
                        changed = true;
                    }
                }
               
                //Говорим что стоянки обновились
                if (changed)
                {
                    if (changeNotifier != null)
                    {
                        changeNotifier.districtsChanged();
                    }
                }
            }
        });
        
        //Грузим список районов
        load();
    }
    
    public void clear()
    {
        //Чистим коллекцию
        districts.removeAllElements();
    }
    
    public final void load()
    {
        //Чистим коллекцию
        districts.removeAllElements();
        
        try
        {
            RecordStore recordStore = RecordStore.openRecordStore(RMS_DISTRICTS_NAME, true);
            RecordEnumeration re = recordStore.enumerateRecords(null, null, false);
            try
            {
                if (re.numRecords() != 0)
                {
                    byte[] data;
                    while (re.hasNextElement())
                    {
                        data = recordStore.getRecord(re.nextRecordId());
                        try
                        {
                            District district = new District(data);
                            if (district.getId() == LAST_UPDATE_TIME_KEY)
                            {
                                latsUpdateTime = Long.parseLong(district.getName());
                            }
                            else
                            {
                                //Сортируем стоянки
                                boolean inserted = false;
                                for (int i = 0; i < districts.size(); ++i)
                                {
                                    if (((District)districts.elementAt(i)).getNumber() >= district.getNumber())
                                    {
                                        districts.insertElementAt(district, i);
                                        inserted = true;
                                        break;
                                    }
                                }
                                
                                if (!inserted)
                                {
                                    districts.addElement(district);
                                }
                            }
                        }catch(Exception ioex){}
                    }
                }
            }
            finally
            {
                re.destroy();
                recordStore.closeRecordStore();
            }
        }catch(RecordStoreException rse){}
    }
    
    public final void save()
    {
        //Удаляем предыдущее хранилище
        try
        {
            RecordStore.deleteRecordStore(RMS_DISTRICTS_NAME);
        }catch(Exception ex){}

        //Сохраняем все данные
        try
        {
            //открываем хранилище
            RecordStore recordStore = RecordStore.openRecordStore(RMS_DISTRICTS_NAME, true);
            try
            {
                byte[] data;
                synchronized(districts)
                {
                    for (int i = districts.size() - 1; i >= 0; --i)
                    {
                        data = ((District)districts.elementAt(i)).toBytes();
                        recordStore.addRecord(data,0,data.length);
                    }
                }

                //Сохраняем время обновления регионов
                District updateTimeTmp = new District(LAST_UPDATE_TIME_KEY, Long.toString(latsUpdateTime));
                data = updateTimeTmp.toBytes();
                recordStore.addRecord(data, 0, data.length);
            }
            finally
            {
                //Закрываем хранилище
                recordStore.closeRecordStore();
            }
        }catch(Exception rse){}
        
        System.gc();
    }

    public void setChangeNotifier(ChangeNotifier changeNotifier)
    {
        this.changeNotifier = changeNotifier;
    }

    public int getDistrictsCount()
    {
        synchronized(districts)
        {
            return districts.size();
        }
    }
    
    public District getDistrictById(int districtId)
    {
        synchronized(districts)
        {
            for (int i = 0; i < districts.size(); ++i)
            {
                if (((District)districts.elementAt(i)).getId() == districtId)
                {
                    return ((District)districts.elementAt(i));
                }
            }
        }
        
        return null;
    }
    
    public District getDistrictByNumber(int number)
    {
        synchronized(districts)
        {
            return ((District)districts.elementAt(number));
        }
    }
    
    public void addDistrict(District district)
    {
        synchronized(districts)
        {
            district.setNumber(districts.size());
            districts.addElement(district);
        }
    }
    
    public long getLatsUpdateTime() 
    {
        return latsUpdateTime;
    }

    public void setLatsUpdateTime(long latsUpdateTime) 
    {
        this.latsUpdateTime = latsUpdateTime;
    }

    public long getServerUpdateTime() 
    {
        return serverUpdateTime;
    }

    public void setServerUpdateTime(long serverUpdateTime) 
    {
        this.serverUpdateTime = serverUpdateTime;
    }

    public interface ChangeNotifier
    {
        public void districtsChanged();
    }
}
